<template>
	<view :class="['v-modal', { active: animateVisible }]" v-if="visible">
		<div class="make" @click="onMaskClick"></div>
		<view :class="['v-modal-content', { active: animateVisible }]">
			<view class="v-modal-title" v-if="title">{{ title }}</view>
			<view :class="['v-modal-main', { center }]">
				<slot>{{ content }}</slot>
			</view>
			<view class="v-modal-button-group" v-if="hasButton">
				<view @click="close" v-if="showCancel" hover-stop-propagation :hover-start-time="0" hover-class="active" class="v-modal-button cancel">
					{{ cancelText }}
				</view>
				<view @click="onConfirm" hover-stop-propagation :hover-start-time="0" hover-class="active" class="v-modal-button confirm">
					<template v-if="loading">
						<u-icon color="#ff4900" size="40rpx" name="reload" class="loading"></u-icon>
					</template>
					<template v-else>{{ confirmText }}</template>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
const DURATION = 300

export default {
	name: "v-modal",
	props: {},
	data() {
		return {
			title: "",
			showCancel: true,
			maskClose: true,
			visible: false,
			loading: false,
			center: false,
			callback: null,
			cancel: null,
			hasButton: true,
			cancelText: "取消",
			confirmText: "确认",
			content: "",

			animateVisible: false,

			resolve: null,
			reject: null,
		}
	},
	computed: {},
	methods: {
		show(options = {}) {
			this.title = options.title || ""
			this.showCancel = options.showCancel ?? true
			this.maskClose = options.maskClose ?? true
			this.hasButton = options.hasButton ?? true
			this.callback = options.confirm
			this.cancel = options.cancel
			this.loading = false
			this.cancelText = options.cancelText || "取消"
			this.confirmText = options.confirmText || "确认"
			this.content = options.content || ""
			this.center = options.center || false

			this.visible = true
			this.$nextTick(() => {
				setTimeout(() => {
					this.animateVisible = true
				}, 0)
			})
			return new Promise((resolve, reject) => {
				this.resolve = resolve
				this.reject = reject
			})
		},
		hide() {
			this.close()
		},
		close() {
			if (this.loading) return
			this.animateVisible = false
			setTimeout(() => {
				this.visible = false
			}, DURATION)
			this.cancel && this.cancel()
			this.reject && this.reject()
		},
		onConfirm() {
			if (this.loading) return
			this.loading = true
			const next = () => {
				this.loading = false

				this.animateVisible = false
				setTimeout(() => {
					this.visible = false
				}, DURATION)
			}
			const cancel = () => {
				this.loading = false
			}

			this.callback && this.callback(next, cancel)
			this.resolve && this.resolve({ next, cancel })
		},
		onMaskClick() {
			if (this.maskClose && !this.loading) {
				this.close()
			}
		},
	},
}
</script>

<style lang="scss" scoped>
.v-modal {
	position: fixed;
	top: 0;
	bottom: 0;
	right: 0;
	left: 0;
	margin: auto;
	background: rgba(#000, 0.55);
	display: flex;
	justify-content: center;
	align-items: center;
	z-index: 99;
	opacity: 0;
	transition: all 0.3s;
	&.active {
		opacity: 1;
	}
	.make {
		position: absolute;
		top: 0;
		bottom: 0;
		right: 0;
		left: 0;
		z-index: 1;
		width: 100%;
		height: 100%;
	}
	.v-modal-content {
		background: #fff;
		border-radius: 30rpx;
		width: 640rpx;
		overflow-x: hidden;
		overflow-y: auto;
		transform: scale(0.9);
		max-height: 60vh;
		transition: all 0.3s;
		position: relative;
		z-index: 3;
		&.active {
			transform: scale(1);
		}
	}
	.v-modal-title {
		line-height: 48rpx;
		font-size: 36rpx;
		padding-top: 50rpx;
		text-align: center;
	}
	.v-modal-main {
		max-height: 60vh;
		overflow-y: auto;
		font-size: 32rpx;
		line-height: 40rpx;
		color: #646566;
		padding-top: 26rpx;
		padding-bottom: 40rpx;
		padding-left: 24rpx;
		padding-right: 24rpx;
		&.center {
			text-align: center;
		}
	}
	.v-modal-button-group {
		display: flex;
		justify-content: space-between;
		align-items: center;
		user-select: none;
		position: relative;
		text-align: center;
		&::after {
			content: "";
			position: absolute;
			top: 0;
			left: 0;
			width: 100%;
			border-top: 1px solid #ebedf0;
		}
		.v-modal-button {
			width: 100%;
			cursor: pointer;
			font-size: 32rpx;
			height: 96rpx;
			line-height: 96rpx;
			position: relative;
			display: flex;
			justify-content: center;
			align-items: center;
			&.confirm {
				color: #ff4900;
				&::after {
					content: "";
					position: absolute;
					left: 0;
					top: 0;
					height: 100%;
					border-left: 1px solid #ebedf0;
				}
				.loading {
					@keyframes loading {
						0% {
							transform: rotate(0deg);
						}
						100% {
							transform: rotate(360deg);
						}
					}
					animation: loading 1s linear infinite;
				}
			}
			&.active {
				background: #e5e5e5;
			}
		}
	}
}
</style>
